package com.harmonyos.samples.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.harmonyos.samples.action.DemoTestAction;
import com.harmonyos.samples.constants.Constants;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

public class HttpRequest {
    public static volatile HttpRequest instance;
    private final CloseableHttpClient httpClient;

    private final PoolingHttpClientConnectionManager connectionManager;

    public static boolean isClosed = false;

    private int retryCount = 0;

    private HttpRequest() {
        connectionManager = new PoolingHttpClientConnectionManager();
        // 设置最大连接数等参数
        connectionManager.setMaxTotal(100);
        connectionManager.setDefaultMaxPerRoute(10);
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(Constants.HTTP_CONNECT_TIMEOUT)
                .setConnectionRequestTimeout(Constants.HTTP_CONNECT_TIMEOUT)
                .setRedirectsEnabled(true)
                .build();
        httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();
    }

    public static HttpRequest getInstance() {
        if (instance == null) {
            synchronized (HttpRequest.class) {
                if (instance == null) {
                    instance = new HttpRequest();
                    isClosed = false;
                }
            }
        } else {
            if (isClosed) {
                if (DemoTestAction.canDownload) {
                    instance = new HttpRequest();
                    isClosed = false;
                }
            }
        }
        return instance;
    }

    public void cancel() {
        try {
            httpClient.close();
            isClosed = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String executeGet(HttpGet httpGet) {
        String result = null;
        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public void download(String downloadPath, String localPath, String... extra) {
        HttpGet httpGet = new HttpGet(downloadPath);
        try (CloseableHttpResponse response = httpClient.execute(httpGet);) {
            HttpEntity entity = response.getEntity();
            if (entity != null && !isClosed) {
                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                byte[] data = new byte[1024];
                int nRead;
                InputStream contentStream = entity.getContent();
                while ((nRead = contentStream.read(data, 0, data.length)) != -1) {
                    buffer.write(data, 0, nRead);
                }
                buffer.flush();
                byte[] bytes = buffer.toByteArray();
                String content = new String(bytes, StandardCharsets.UTF_8);
                if (content.endsWith("Route error: Incorrect authorization result")) {
                    Thread.sleep(1000);
                    retryCount++;
                    if (retryCount <= 3) {
                        download(downloadPath, localPath, extra);
                        return;
                    }
                }
                retryCount = 0;
                if (localPath.endsWith("hvigorfile.ts") || localPath.endsWith("Index.ets")
                        || localPath.endsWith("oh-package.json5") || localPath.toLowerCase().endsWith("README.md".toLowerCase())) {
                    content = deleteCode(content, localPath, extra);
                    Files.writeString(Path.of(localPath), content);
                } else {
                    long length = Files.copy(contentStream, Path.of(localPath), StandardCopyOption.REPLACE_EXISTING);
                    if (length == 0) {
                        Files.writeString(Path.of(localPath), content);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public String deleteCode(String content, String path, String... extra) {
        if (path.endsWith("hvigorfile.ts")) {
            String[] deleteList = {
                    "import { PluginConfig, etsGeneratorPlugin } from '@app/ets-generator';",
                    "etsGeneratorPlugin(config)",
                    "const config: PluginConfig = {\n" +
                            "    scanFiles: [\"src/main/ets/FeatureComponent\"],\n" +
                            "}",
                    "const config: PluginConfig = {\n" +
                            "    scanFiles: [\"src/main/ets/FeatureComponent\"],\n" +
                            "}",
            };
            content = delete(content, deleteList);
            return content;
        }
        if (path.endsWith("Index.ets")) {
            content = delete(content, "export * from './src/main/ets/generated/RouterBuilder';");
            return content;
        }
        if (path.endsWith("oh-package.json5")) {
            content = Json5Parser.parseJson5(content);
            JsonObject jsonObject = JsonParser.parseString(content).getAsJsonObject();
            if (jsonObject.has("dependencies")) {
                JsonObject dependenciesObject = jsonObject.get("dependencies").getAsJsonObject();
                dependenciesObject.remove("@ohos/dynamicsrouter");
                dependenciesObject.remove("@ohos/dynamicsRouter");
                dependenciesObject.remove("@ohos/base");
                dependenciesObject.remove("utils");
                dependenciesObject.remove("routermodule");
            }
            try {
                ObjectMapper mapper = new ObjectMapper();
                content = mapper.writerWithDefaultPrettyPrinter()
                        .writeValueAsString(mapper.readValue(jsonObject.toString(), Object.class));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return content;
        }
        if (path.toLowerCase().endsWith("README.md".toLowerCase())) {
            if (extra != null && extra.length > 0) {
                String gifPath = extra[0];
                if (gifPath != null && !gifPath.isEmpty()) {
                    String gifName = InsertUtils.getFileNameFromUrl(gifPath);
                    String needReplaceStr = "../../product/entry/src/main/resources/base/media/" + gifName;
                    String gifLocalPath = path.substring(0, path.lastIndexOf("/") + 1) + gifName;
                    download(gifPath, gifLocalPath);
                    while (content.contains(needReplaceStr)) {
                        content = content.replace(needReplaceStr, gifName);
                    }
                    return content;
                }
            }
        }
        return content;
    }

    private String delete(String content, String... replaces) {
        if (replaces != null) {
            for (String replace : replaces) {
                content = content.replace(replace, "");
            }
        }
        while (content.contains("\n\n\n")) {
            content = content.replace("\n\n\n", "");
        }
        return content;
    }
}
